﻿using EMall.Domain;

namespace EMall.ProductService.Categories
{
    public class CategoryManager : DomainService
    {
        private readonly ICategoryRepository _categoryRepository;
        public CategoryManager(ICategoryRepository categoryRepository)
        {
            _categoryRepository = categoryRepository;
        }
        public async Task<string> CheckNameExistsAsync(string name)
        {
            var existing = await _categoryRepository.GetByNameAsync(name);
            if (existing != null)
            {
                throw new Exception($"name {name} has already exists!");
            }
            return name;
        }
        public async Task<string> CheckNewNameExistsAsync(Category category, string name)
        {
            if (category.Name == name)
            {
                return name;
            }
            return await CheckNameExistsAsync(name);
        }
        public async Task<string> GenerateCodeAsync(int parentId)
        {
            var parent = await _categoryRepository.GetAsync(parentId);
            var lastChild = await _categoryRepository.GetLastChildByParentIdAsync(parentId);
            return GenerateCode(parent?.Code, lastChild?.Code);
        }
        public async Task<string> GenerateNewCodeAsync(Category category, int newParentId)
        {
            if (category.ParentId == newParentId)
            {
                return category.Code;
            }
            return await GenerateCodeAsync(newParentId);
        }
        #region GenerateCode
        private string GenerateCode(string? parentCode, string? lastChildCode)
        {
            var lastCode = string.IsNullOrWhiteSpace(lastChildCode) ? string.Empty : lastChildCode.Split('.').Last();
            int.TryParse(lastCode, out int nextNumber);
            var childCode = CreateCode(nextNumber + 1);
            return string.IsNullOrWhiteSpace(parentCode) ? childCode : $"{parentCode}.{childCode}";
        }
        private string CreateCode(params int[] numbers)
        {
            return numbers.Any() ? string.Join(".", numbers!.Select(number => $"{number:D5}")) : string.Empty;
        }
        private string GetParentCode(string childCode)
        {
            var splittedCode = childCode.Split('.');
            return string.Join(".", splittedCode.Take(splittedCode.Length - 1));
        }
        #endregion
    }
}